package com.irdstudio.efp.rule.service.util;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

import com.irdstudio.efp.rule.common.enumeration.CreditCardType;
import com.irdstudio.efp.rule.common.enumeration.LoanStatus;
import com.irdstudio.efp.rule.common.enumeration.TelAprvQResult;
import com.irdstudio.efp.rule.service.vo.CreditCardEntity;
import com.irdstudio.efp.rule.service.vo.CreditCardOverdueEntity;
import com.irdstudio.efp.rule.service.vo.CreditQueryEntity;
import com.irdstudio.efp.rule.service.vo.CreditRepaymentEntity;
import com.irdstudio.efp.rule.service.vo.PayTaxUnitEntity;
import com.irdstudio.efp.rule.service.vo.TelAprvCfg;
import com.irdstudio.efp.rule.service.vo.TelAprvResult;


public class RuleUtil {
	
	private static final SimpleDateFormat MONTH_SDF = new SimpleDateFormat("yyyyMM");
	private static final SimpleDateFormat DAY_SDF = new SimpleDateFormat("yyyyMMdd");
	
	public static final String PARAM = "Param";
	public static final String VALUE = "Value";
	/** 交易备注的: 敏感字段值 */
	public static final String SENSITIVE_REMARK = "股票、基金、理财、黄金、票据、房、三方、银转证、中介、置业、物业、经纪、证券、投资、实业、资产、担保、资本金、首期、首付款、融资";
	/** 摘要范围的: 敏感摘要代码值 */
	public static final String SENSITIVE_SUMMARY = "01GL、01ml、01tf、01vk、01b0、01vn、12D3、12EH、12ml、01DH、01az、01vm、01bq、12c9、12vm、01rl、12H2、01H2、01td、12DH、12az、12gi、12hw、12rl、01D3、01EH、01kR、12FW、12GL、12b0、12kR、12z9、12XR、12bq、12iw、12td";
	/**
	 * 获得所有逾期信息
	 * @param cards
	 * @return
	 */
	public static List<CreditCardOverdueEntity> getAllovers(List<CreditCardEntity> cards) {
		List<CreditCardOverdueEntity> overs = new ArrayList<>();
		List<CreditCardOverdueEntity> temps;
		if ( cards != null && cards.size() > 0) {
			for ( int i = 0; i < cards.size(); i++) {
				if ( null != cards.get(i).getOverdueInfos() 
						&& cards.get(i).getOverdueInfos().size() > 0 ) {
					//添加标准判断日期
					temps = cards.get(i).getOverdueInfos();
					for (CreditCardOverdueEntity over : temps) {
						over.setStandDate(cards.get(i).getEndYearMonth());
						over.setCardNo(cards.get(i).getCardNo());
					}
					overs.addAll( temps );
				}
			} 
		}
		
		return overs;
	}
	/**
	 * 根据卡类型获得所有逾期信息
	 * @param cards
	 * @return
	 */
	public static List<CreditCardOverdueEntity> getAllOversByType(List<CreditCardEntity> cards, CreditCardType cardType) {
		List<CreditCardOverdueEntity> overs = new ArrayList<>();
		List<CreditCardOverdueEntity> temps;
		if ( cards != null && cards.size() > 0) {
			CreditCardEntity card;
			for ( int i = 0; i < cards.size(); i++) {
				card = cards.get(i);
				if ( null != card.getOverdueInfos() && card.getCardType() == cardType
						&& card.getOverdueInfos().size() > 0 ) {
					temps = cards.get(i).getOverdueInfos();
					for (CreditCardOverdueEntity over : temps) {
						over.setStandDate(cards.get(i).getEndYearMonth());
						over.setCardNo(cards.get(i).getCardNo());
					}
					overs.addAll( temps );
				}
			} 
		}
		
		return overs;
	}
	
	/**
	 * 根据卡类型获得所有逾期信息
	 * @param cards
	 * @return
	 */
	public static List<CreditCardOverdueEntity> getAllOversByType(List<CreditCardEntity> cards, CreditCardType cardType, CreditCardType deCardType) {
		List<CreditCardOverdueEntity> overs = new ArrayList<>();
		List<CreditCardOverdueEntity> temps;
		if ( cards != null && cards.size() > 0) {
			CreditCardEntity card;
			for ( int i = 0; i < cards.size(); i++) {
				card = cards.get(i);
				if ( null != card.getOverdueInfos() 
						&& (card.getCardType() == cardType || card.getCardType() == deCardType )
						&& card.getOverdueInfos().size() > 0 ) {
					temps = cards.get(i).getOverdueInfos();
					for (CreditCardOverdueEntity over : temps) {
						over.setStandDate(cards.get(i).getEndYearMonth());
						over.setCardNo(cards.get(i).getCardNo());
					}
					overs.addAll( temps );
				}
			} 
		}
		
		return overs;
	}
	/**
	 * 获取所有的还款记录
	 * @param cards
	 * @return
	 */
	public static List<CreditRepaymentEntity> getAllRepays(List<CreditCardEntity> cards) {
		List<CreditRepaymentEntity> repays = new ArrayList<>();
		List<CreditRepaymentEntity> temps;
		if ( cards != null && cards.size() > 0) {
			for ( int i = 0; i < cards.size(); i++) {
				if ( null != cards.get(i).getRepayInfos() 
						&& cards.get(i).getRepayInfos().size() > 0 ) {
					temps = cards.get(i).getRepayInfos();
					for (CreditRepaymentEntity repay : temps) {
						repay.setStandDate(cards.get(i).getEndYearMonth());
					}
					repays.addAll( cards.get(i).getRepayInfos() );
				}
			} 
		}
		return repays;
	}
	/**
	 * 日期是否在 month 个月内
	 * @param date 日期
	 * @param month 月数
	 * @return
	 */
	public static boolean isMonthBetween(String date, Object month, String standDate) {
		int m = 0;
		boolean flag = false;
		try {
			m = Integer.parseInt(month.toString());
			date = executeDate(date, 6);
			Date time = MONTH_SDF.parse(date);
			Calendar nowCal = Calendar.getInstance();
			if ( StringUtils.isNotEmpty(standDate) ) {
				standDate = executeDate(standDate, 6);
				Date stand = MONTH_SDF.parse(standDate);
				nowCal.setTime(stand);
			}
			Calendar dateCal = Calendar.getInstance();
			dateCal.setTime(time);
			//计算两个日期相差的月份
			int diffMonth = (nowCal.get(Calendar.YEAR) - dateCal.get(Calendar.YEAR) ) * 12
					+ (nowCal.get(Calendar.MONTH) - dateCal.get(Calendar.MONTH) );
			if (diffMonth < m) {
				flag = true;
			}
		} catch (Exception e) {
		}
		return flag;
	}
	
	/**
	 * 
	 * @param regex 正则表达式
	 * @param str 
	 * @return
	 */
	public static boolean isMatches(String regex, String str) {
		if (null == str ) return false;
		boolean flag = Pattern.matches(regex, str);
		return flag;
	}
	/**
	 * 贷款机构总数
	 * @return
	 */
	public static int loanBankTotal(List<CreditCardEntity> cards) {
		int banks = 0;
		Map<String, Integer> temp = new HashMap<>();
		if (null != cards && cards.size() > 0) {
			CreditCardEntity card;
			for ( int i = 0; i < cards.size(); i++) {
				card = cards.get(i);
				if (card.getCardType() == CreditCardType.DEBIT_CARD 
						|| card.getCardType() == CreditCardType.SEMI_CREDIT_CARD ) {
					continue;
				}
				if ( null == temp.get(card.getBankNo()) ) {
					banks++;
					temp.put(card.getBankNo(), 1);
				}else {
					temp.put(card.getBankNo(),  temp.get(card.getBankNo()) + 1);
				}
			}
		}
		
		return banks;
	}
	/**
	 * 征信记录中未结清贷款的他行放款机构之和
	 * @return
	 */
	public static int noCloLoanBankTotal(List<CreditCardEntity> cards) {
		int banks = 0;
		Map<String, Integer> temp = new HashMap<>();
		if (null != cards && cards.size() > 0) {
			CreditCardEntity card;
			for ( int i = 0; i < cards.size(); i++) {
				card = cards.get(i);
				if ( card == null )
					continue;
				if (card.getCardType() == CreditCardType.DEBIT_CARD 
						|| card.getCardType() == CreditCardType.SEMI_CREDIT_CARD ) {
					continue;
				}
				if ( RuleUtil.isMatches("^[a-zA-Z0-9]+$", card.getBankNo()) && 
						card.getLoanStatus() != LoanStatus.CLOSE_OVER) {
					if ( null == temp.get(card.getBankNo()) ) {
						banks++;
						temp.put(card.getBankNo(), 1);
					}else {
						temp.put(card.getBankNo(),  temp.get(card.getBankNo()) + 1);
					}
				}
			}
		}
		
		return banks;
	}
	/**
	 * 通过电核结果集合获得不同问题类型的通过率
	 * @param rlts 电核结果集合
	 * @return
	 */
	public static Map<String, Double> getTelAprvQTypePassRate(List<TelAprvResult> rlts) {
		Map<String, Double> map = new HashMap<>();
		if ( null != rlts && rlts.size() > 0) {
			TelAprvResult rlt;
			double total = 0.0;
			double passTotal = 0.0;
			for (int i = 0; i < rlts.size(); i++) {
				rlt = rlts.get(i);
				if ( null == map.get(rlt.getqType()) ) {
					if ( rlt.getqRtl() == TelAprvQResult.PASS) {
						passTotal = 1.0;
					}else {
						passTotal = 0.0;
					}
					total = 1.0;
					map.put(rlt.getqType() + "PassTotal", passTotal); //通过总数
					map.put(rlt.getqType() + "Total", total); //问题总数 
					map.put(rlt.getqType(), (passTotal / total) * 100 ); //通过率
				}else {
					total = map.get(rlt.getqType() + "Total") + 1; //问题总数 
					passTotal = map.get(rlt.getqType() + "PassTotal"); //通过总数
					if ( rlt.getqRtl() == TelAprvQResult.PASS) {
						passTotal += 1;
					}
					map.put(rlt.getqType() + "PassTotal", passTotal); //通过总数
					map.put(rlt.getqType() + "Total", total); //问题总数 
					map.put(rlt.getqType(), (passTotal / total) * 100 ); //通过率
				}
			}
		}
		return map;
	}
	/**
	 * 通过电核配置集合,获取不通过的问题总数
	 * @param cfgs 电核配置集合
	 * @param qTypeRate 不同问题类型的不同通过率 Map
	 * @return
	 */
	public static int getNoPassTotal(List<TelAprvCfg> cfgs, Map<String, Double> qTypeRate) {
		if ( null == qTypeRate || qTypeRate.size() == 0 ) return -1;
		int total = 0;
		if ( null != cfgs && cfgs.size() > 0 ) {
			TelAprvCfg cfg;
			Double passRate;
			for (int i = 0; i < cfgs.size(); i++ ) {
				cfg = cfgs.get(i);
				passRate = qTypeRate.get(cfg.getqType());
				//如果存在问题通过率， 并且小于
				if ( null != passRate && null != cfg.getPassRate()
						&& passRate < cfg.getPassRate().doubleValue() ) {
					total++;
				}
			}
		}
		return total;
	}
	/**
	 * 是否距离上次征信查询 已经过去 creditQueryTremDay 日
	 * @param querys
	 * @param creditQueryTremDay
	 * @return
	 */
	public static boolean isStartCreditQuery(List<CreditQueryEntity> querys, Object creditQueryTremDay) {
		boolean flag = false;
		if ( null != querys && querys.size() > 0 ) {
			Date temp = new Date();
			Date lastQuery = new Date(); //最后的查询日期
			
			try {
				String queryDate;
				//获取征信最后的查询日期
				for ( int i = 0; i < querys.size(); i++ ) {
					queryDate = querys.get(i).getQueryDate();
					queryDate = executeDate(queryDate, 8);
					lastQuery = DAY_SDF.parse(queryDate);
					if ( i > 0) {
						temp = DAY_SDF.parse(queryDate);
						if ( temp.getTime() > lastQuery.getTime()) {
							lastQuery = temp;
						}
					}
				}
				int day = Integer.parseInt(creditQueryTremDay.toString());
				Calendar lastCal = Calendar.getInstance();
				lastCal.setTime(lastQuery);
				lastCal.add(Calendar.DAY_OF_MONTH, day);
				Date now = new Date();
				//如果最后的查询日期 加上 N天, 小于或等于今天
				if ( lastCal.getTime().getTime() <= now.getTime() ) {
					flag = true;
				}
				
			} catch (Exception e) {
			}
			
		}
		return flag;
	} 
	/**
	 * 当前日期是否是本月
	 * @param date
	 * @return
	 */
	public static boolean isCurrentTermDate(String date) {
		boolean flag = false;
		try {
			date = executeDate(date, 6);
			Date overDate = MONTH_SDF.parse(date);
			Calendar overCal = Calendar.getInstance();
			overCal.setTime(overDate);
			Calendar cal = Calendar.getInstance();
			//如果逾期的年,月 跟 当前的年,月 一致,则认为是当前 逾期信息
			if ( overCal.get(Calendar.YEAR) == cal.get(Calendar.YEAR)
					&& overCal.get(Calendar.MONTH) == cal.get(Calendar.MONTH)) {
				flag = true;
			}
		} catch (Exception e) {
			flag = false;
		}
		return flag;
	}
	/**
	 * 是否包含敏感字段
	 * @param info 信息
	 * @param sensitiveParam 敏感字段(使用、号隔开,如: 股票、基金、理财、黄金、票据、房、三方)
	 * @return
	 */
	public static boolean isContainsSensitive(String info, String sensitiveParam) {
		boolean flag = false;
		if ( !StringUtils.isEmpty(info) ) {
			String[] sensitives = sensitiveParam.split("、");
			for (int i = 0; i < sensitives.length; i++) {
				if ( info.contains(sensitives[i])) {
					flag = true;
					break;
				}
			}
			
		}
		return flag;
	}
	/**
     * 比较两个日期的相隔天数<br>
     * 比较方式：date2 减 date1
     * 
     * @param date1
     * @param date2
     * @return 返回绝对天数 (如果 date2 比 date1 也是返回 正数), 小于0,则是发生异常
     */
	public static int  getDaysBetweenTwoDates(String date1, String date2) {  
		int result = 0;
	    try {
	    	date1 = executeDate(date1, 8);
	    	date2 = executeDate(date2, 8);
	        long d1 = DAY_SDF.parse(date1).getTime();
	        long d2 = DAY_SDF.parse(date2).getTime();

	        result = (int) ((d2 - d1) / 1000 / 60 / 60 / 24);
	        result = result < 0 ? result * -1 : result;
	    } catch (Exception e) {
	        result = -1;
	    }
	    return result;
    }
    /**
     * 比较两个日期的相隔天数<br>
     * 比较方式：date2 减 date1
     *
     * @param date1 日期1
     * @param date2 日期2
     * @return 相差天数
     */
	public static int  getRealDaysBetweenTwoDates(String date1, String date2) {
		int result = 0;
	    try {
	    	date1 = executeDate(date1, 8);
	    	date2 = executeDate(date2, 8);
	        long d1 = DAY_SDF.parse(date1).getTime();
	        long d2 = DAY_SDF.parse(date2).getTime();

	        result = (int) ((d2 - d1) / 1000 / 60 / 60 / 24);
	    } catch (Exception e) {
	        result = -1;
	    }
	    return result;
    }
	/**
     * 获得两个时间之间相差的月份，如天数未对应，则不算满一个月
     * @param date1 开始时间
     * @param date2 结束时间
     * @return
     */
    public static int getMonthsBetweenTwoDates(String date1, String date2) {
        int result = 0;
        try {

        	Calendar c1 = Calendar.getInstance();
            Calendar c2 = Calendar.getInstance();
            date1 = executeDate(date1, 6);
	    	date2 = executeDate(date2, 6);
            c1.setTime(MONTH_SDF.parse(date1));
            c2.setTime(MONTH_SDF.parse(date2));

            result = (c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR)) * 12 + c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);
            
        } catch (Exception e) {
            result = -1;
        }
        return result;
    }
    /**
     * 处理日期类型, 去掉非数字字符,并且返回指定长度的日期字符串
     * @param date
     * @param length
     * @return
     */
    public static String executeDate(String date, int length) {
    	String result = null;
    	try {
    		//去掉非数字字符 
    		result = date.replaceAll("\\D", "");
    		result = result.substring(0, length);
		} catch (Exception e) {
		}
    	
    	return result;
    }
    /**
     * 将逾期数组按小到大排序
     * @return
     */
    public static List<CreditCardOverdueEntity> sortSmallCardOver(List<CreditCardOverdueEntity> overs) {
    	if ( null == overs || overs.size() == 0 ) return overs;
    	int size = overs.size();
    	List<CreditCardOverdueEntity> resOvers = new ArrayList<>(size);
    	int l = 0;
    	CreditCardOverdueEntity min;
    	CreditCardOverdueEntity temp;
    	for (int i = 0; i < size; i++) {
    		min = overs.get(0);
    		l = 0;
    		for (int j = 1; j < overs.size(); j++) {
    			temp = overs.get(j);
    			if ( temp == null) continue;
    			if ( monthDateToInt(temp.getOverDueDate()) < monthDateToInt(min.getOverDueDate()) ) {
    				min = temp;
    				l = j;
    			}
    		}
    		resOvers.add(min);
    		overs.remove(l);
    	}
  
    	return resOvers;
    }
    /**
     * 将年月日期转换为数字
     * @param date
     * @return
     */
    public static int monthDateToInt(String date) {
    	int i = 0;
    	try {
    		if ( null != date ) {
    			date = executeDate(date, 6);
    			i = Integer.parseInt(date);
    		}
		} catch (Exception e) {
		}
    	return i;
    }
    /**
     * 存放参数
     * @param param
     * @param val
     * @param ruleParams
     * @return
     */
    public static boolean putParamInfo(String param, String val, Map<String, String> ruleParams){
    	if (null != ruleParams) {
    		ruleParams.put(param + RuleUtil.PARAM, val);
    	}
    	return true;
    }
    /**
     * 存放参数值
     * @param param
     * @param val
     * @param ruleParams
     * @return
     */
    public static boolean putValInfo(String param, String val, Map<String, String> ruleParams){
    	if (null != ruleParams) {
    		ruleParams.put(param + RuleUtil.VALUE, val);
    	}
    	return true;
    }
    /**
     * date是否大于standDay + addDay, 
     * @param date 日期
     * @param standDay 比较日期
     * @param addDays 相加天数
     * @return
     */
    public static boolean isStandDayBig(String date, String standDay, int addDays) {
    	boolean flag = false;
    	try {
    		date = executeDate(date, 6);
    		standDay = executeDate(standDay, 8);
    		Date standDate = DAY_SDF.parse(standDay);
    		Calendar standCal = Calendar.getInstance();
    		standCal.setTime(standDate);
    		standCal.add(Calendar.DAY_OF_MONTH, addDays);
    		Date d = MONTH_SDF.parse(date);
    		Calendar cal = Calendar.getInstance();
    		cal.setTime(d);
    		//计算两个日期相差的月份
			int diffMonth = (cal.get(Calendar.YEAR) - standCal.get(Calendar.YEAR) ) * 12
					+ (cal.get(Calendar.MONTH) - standCal.get(Calendar.MONTH) );
			flag = diffMonth >= 0;
    	}catch(Exception e) {
    	}
    	return flag;
    }
    /**
     * 两个日期 相差的年月等于1
     * @param date1 新日期
     * @param date2 旧日期
     * @return
     */
    public static boolean twoDateMonthDiff(String date1, String date2) {
    	int diff = 0;
    	try {
    		diff = getMonthsBetweenTwoDates(date2, date1);;
    	}catch (Exception e) {
		}
    	
    	return diff == 1;
    }

	/**
	 * 获取日期的年月
	 * @param date 日期
	 * @return 年月字符串
	 */
	public static String getYearMonth(String date) {
		String result = null;
		try {
			//去掉非数字字符
			result = date.replaceAll("\\D", "");
			result = result.substring(0, 6);
		} catch (Exception e) {
			result = null;
		}

		return result;
	}

	/**
	 * 获取日期的年月 Integer 类型
	 */
	public static Integer getYearMonthInt(String date) {
		String ym;
		Integer result = null;
		try {
			//去掉非数字字符
			ym = date.replaceAll("\\D", "");
			ym = ym.substring(0, 6);
			result = Integer.valueOf(ym);
		} catch (Exception e) {
		}

		return result;
	}

	/**
	 * 获取代扣代缴单位注册类型代码
	 * @param uniform 统一社会信用代码
	 * @param payTaxUnits 统一社会信用代码
	 * @return 代扣代缴单位注册类型代码
	 */
	public static String getTaxType(String uniform, List<PayTaxUnitEntity> payTaxUnits) {
		if (StringUtils.isEmpty(uniform)) return null;
		if ( null != payTaxUnits && payTaxUnits.size() > 0){
			for (PayTaxUnitEntity payTax: payTaxUnits) {
				if ( uniform.equals(payTax.getUniformSociCreditCode()) ) {
					return payTax.getTaxType();
				}
			}
		}
		return null;
	}
}

